using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;

//ToDo:
//  Fix Tree control loading for more than 2 levels <Done 25 MAR 2007>
//  About box and hook it up to the menu <Done 26 MAR 2007>
//  Add config dialog and hook it up to the menu (including persistence) <Done 29 MAR 2007>
//  Add configured destinations to combo box from persisted config (including remembering the last chosen destination) <Done 30 MAR 2007>
//  Add file add menu item <Done 16 APR 2007>
//  Add file drag and drop <Done 29 MAR 2007>
//  Add files thumbnails to main dialog area <Done 29 MAR 2007>
//  Add file details and upload button <Done 31 MAR 2007>
//  Add upload progress meter <Done 11 APR 2007>
//  Add album option <Done>

//  Update icon for the main dialog and the About Box image
//  Add download of current pictures in chosen album
//  Add picture rotation option
//  Add album properties handling

namespace Pix2Gallery2
{
    public partial class UploadForm : Form
    {

        private Pix2Gallery2Settings pix2gallery2Settings;
        private Gallery2Interface G2int;
        private NameValueCollection nvColl;
        private NameValueCollection nvExistingPictures;
        private bool downloadedExisting = false;
        private bool success;
        
        public int numFailed;
        
        public UploadForm()
        {
            InitializeComponent();
        }

        private void UploadForm_Load(object sender, EventArgs e)
        {
            string newPath = Path.GetTempPath() + @"Pix2Gallery2\";
            Directory.CreateDirectory(newPath);  
            
            //Initialize the trace listener to output to a file...
            // Creates the text file that the trace listener will write to.
            FileStream myTraceLog = new FileStream(newPath + @"Pix2Gallery2Log.txt", FileMode.Create);
            // Create the new trace listener.
            TextWriterTraceListener myListener = new TextWriterTraceListener(myTraceLog);
            // Add to the TraceListenersCollection
            Trace.Listeners.Add(myListener);
        }

        private void UploadForm_Shown(object sender, EventArgs e)
        {
            pix2gallery2Settings = new Pix2Gallery2Settings();
            if (this.pix2gallery2Settings.LoadAppSettings())
            {
                //Load the Combobox
                if (this.pix2gallery2Settings.Gallery2Urls.Count > 0)
                {
                    this.comboBoxGalleries.BeginUpdate();
                    this.comboBoxGalleries.Items.Clear();
                    foreach (Gallery2Url G2Url in pix2gallery2Settings.Gallery2Urls)
                    {
                        this.comboBoxGalleries.Items.Add(G2Url.m_GalleryTitle);
                    }
                    if (pix2gallery2Settings.DefaultGalleryUrl != "")
                    {
                        this.comboBoxGalleries.Text = pix2gallery2Settings.DefaultGalleryUrl;
                    }
                    this.comboBoxGalleries.EndUpdate();
                    this.comboBoxGalleries.Enabled = true;
                }
                else
                {
                    this.comboBoxGalleries.Enabled = false;
                    MessageBox.Show("Please configure at least one Gallery URL", "Pix2Gallery2");
                    this.optionsToolStripMenuItem_Click(null, null);
                }
            }
            else
            {
                this.comboBoxGalleries.Enabled = false;
                MessageBox.Show("Please configure at least one Gallery URL", "Pix2Gallery2");
                this.optionsToolStripMenuItem_Click(null, null);
            }

            this.comboBoxPictureSize.SelectedIndex = 0;
        }
        
        private void loginButton_Click(object sender, EventArgs e)
        {
            this.treeViewAlbums.Nodes.Clear();
            this.treeViewAlbums.Refresh();
            this.listViewPix.Enabled = false;
            this.toolStripStatusLabel.Text = "";
            this.statusStrip.Refresh();
            this.labelChooseAlbum.Text = "3. Pictures to Add to Chosen Album (Drag and Drop or File-Open)";
            Application.DoEvents();

            Uri G2URL = null;
            string uname = "";
            string pword = "";

            foreach (Gallery2Url g2Url in this.pix2gallery2Settings.Gallery2Urls)
            {
                if (g2Url.m_GalleryTitle == this.comboBoxGalleries.Text)
                {
                    G2URL = new Uri(g2Url.m_GalleryUrl);
                    uname = g2Url.m_GalleryUserName;
                    pword = g2Url.m_GalleryPassword;
                    break;
                }
            }

            this.Cursor = Cursors.WaitCursor;

            G2int = new Gallery2Interface(G2URL);

            //Login to Gallery2 and message login status
            if (G2int.LoginToGallery2(uname, pword))
            {
                this.toolStripStatusLabel.Text = "Login as " + uname + " successful!";
                this.statusStrip.Refresh();
                this.uploadToolStripMenuItem.Enabled = true;
                GetAndLoadAlbumsIntoTreeControl();
            }
            else
            {
                this.toolStripStatusLabel.Text = "Failure! Login as " + uname + " unsuccessful!";
                this.statusStrip.Refresh();
            }

            this.Cursor = Cursors.Default;
        }

        private void SetAlbumList(NameValueCollection nvColl)
        {
            this.nvColl = nvColl;
        }

        private void GetAndLoadAlbumsIntoTreeControl()
        {
            this.labelChooseAlbum.Text = "3. Pictures to Add to Chosen Album (Drag and Drop or File-Open)";

            SetAlbumList(null);

            GetAlbumListThread getAlbumListThread = new GetAlbumListThread(this.G2int, new GetAlbumListCallback(SetAlbumList));
            Thread t = new Thread(new ThreadStart(getAlbumListThread.ThreadProc));

            t.Start();
            t.Join();
            t = null;
 
            //Display the Gallery album list (label1)
            if (this.nvColl != null && this.nvColl["status"] == "0")
            {
                LoadAlbumsIntoTreeControl(this.nvColl);

            }
        }

        private void LoadAlbumsIntoTreeControl(NameValueCollection nvColl)
        {
            Cursor.Current = Cursors.WaitCursor;

            this.treeViewAlbums.ContextMenuStrip = this.contextMenuAddAlbum;

            this.treeViewAlbums.BeginUpdate();
            this.treeViewAlbums.Nodes.Clear();

            int albumCount = Convert.ToInt32(nvColl["album_count"]);
            int albumsAdded = 0;

            for (int i = 1; i <= albumCount; i++)
            {
                string albumParentName = "album.parent." + i.ToString();
                string albumNameKey = "album.name." + i.ToString();
                string albumTitleKey = "album.title." + i.ToString();

                if (nvColl[albumParentName] == "0")
                {
                    albumsAdded += 1;
                    TreeNode newNode = new TreeNode(nvColl[albumTitleKey]);
                    newNode.Name = nvColl[albumNameKey];
                    this.treeViewAlbums.Nodes.Add(newNode);
                    albumsAdded = LoadChildAlbums(nvColl, newNode, albumsAdded);
                }
                if (albumsAdded == albumCount) break;
            }

            this.treeViewAlbums.ExpandAll();
            this.treeViewAlbums.EndUpdate();
            this.treeViewAlbums.Enabled = true;
            Cursor.Current = Cursors.Default;
        }

        private int LoadChildAlbums(NameValueCollection nvColl, TreeNode parentNode, int albumsAdded)
        {
            int albumCount = Convert.ToInt32(nvColl["album_count"]);
            int lalbumsAdded = albumsAdded;

            for (int i = 1; i <= albumCount; i++)
            {
                string albumParentName = "album.parent." + i.ToString();
                string albumNameKey = "album.name." + i.ToString();
                string albumTitleKey = "album.title." + i.ToString();
                string albumParent = nvColl[albumParentName];

                if (albumParent == parentNode.Name)
                {
                    lalbumsAdded += 1;
                    TreeNode newNode = new TreeNode(nvColl[albumTitleKey]);
                    newNode.Name = nvColl[albumNameKey];
                    parentNode.Nodes.Add(newNode);
                    LoadChildAlbums(nvColl, newNode, albumsAdded);
                }
            }

            return lalbumsAdded;

        }

        private void comboBoxGalleries_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.pix2gallery2Settings.DefaultGalleryUrl = this.comboBoxGalleries.Text;
            if (this.comboBoxGalleries.Text == "") this.loginButton.Enabled = false;
            else this.loginButton.Enabled = true;
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBoxPix2Gallery2 aboutBox = new AboutBoxPix2Gallery2();
            aboutBox.ShowDialog();
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OptionsForm optionsForm = new OptionsForm();
            optionsForm.pix2gallery2Settings = this.pix2gallery2Settings;
            optionsForm.ShowDialog();

            this.comboBoxGalleries.Items.Clear();
            this.comboBoxGalleries.Text = "";
            this.comboBoxGalleries.Enabled = false;
            this.loginButton.Enabled = false;
            this.treeViewAlbums.Nodes.Clear();
            this.listViewPix.Enabled = false;
            this.toolStripStatusLabel.Text = "";
            
            //Re-Load the Combobox
            if (pix2gallery2Settings.Gallery2Urls != null && pix2gallery2Settings.Gallery2Urls.Count > 0)
            {
                this.comboBoxGalleries.BeginUpdate();
                foreach (Gallery2Url G2Url in pix2gallery2Settings.Gallery2Urls)
                {
                    this.comboBoxGalleries.Items.Add(G2Url.m_GalleryTitle);
                }
                if (pix2gallery2Settings.DefaultGalleryUrl != "")
                {
                    this.comboBoxGalleries.Text = pix2gallery2Settings.DefaultGalleryUrl;
                }
                this.comboBoxGalleries.EndUpdate();
                this.comboBoxGalleries.Enabled = true;
            }
        }

        private void listViewPix_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            this.labelCaption.Enabled = true;
            this.textBoxCaption.Enabled = true;

            foreach (ListViewItem lvItem in this.listViewPix.SelectedItems)
            {
                this.textBoxCaption.Text = lvItem.Text;
            }
        }
        
        private void listViewPix_AfterLabelEdit(object sender, LabelEditEventArgs e)
        {
            if (this.listViewPix.Items[e.Item].Selected == true)
            {
                this.textBoxCaption.Text = e.Label;
            }
        }

        private void listViewPix_DragDrop(object sender, DragEventArgs e)
        {
            // transfer the filenames to a string array
            // (yes, everything to the left of the "=" can be put in the 
            // foreach loop in place of "files", but this is easier to understand.)
            string[] filesDragged = (string[])e.Data.GetData(DataFormats.FileDrop);
            
            int nonJpeg = 0;
            // loop through the string array, adding each filename to the ListBox
            foreach (string fileDragged in filesDragged)
            {
                if (!AddFileToListView(fileDragged)) nonJpeg++;
            }

            if (nonJpeg > 0)
            {
                Trace.WriteLine("DragDrop: Only JPEG files supported. Count of non-JPEG files that were not added is: " + nonJpeg);
                MessageBox.Show("Sorry, only JPEG files supported. Count of non-JPEG files that were not added is: " + nonJpeg);
            }
        }

        private bool AddFileToListView(string fileTitle, string imageKey, string fileName, string sCaption, bool bJpegCheck, bool bChecked)
        {
            //Check if the file is a jpeg
            if (bJpegCheck)
            {
                string fileExt = Path.GetExtension(fileName);
                fileExt = fileExt.ToUpper();
                if (fileExt != ".JPG" && fileExt != ".JPEG")
                {
                    Trace.WriteLine("AddFileToListView: " + fileName + " was not a JPEG");
                    return false;
                }
            }

            // MAT: moved allocation of LargeImageList to Designer
            // MAT: created allocation of StateImageList in Designer
            //if (this.listViewPix.LargeImageList == null)
            //{
            //    this.listViewPix.LargeImageList = new ImageList();
            //    this.listViewPix.LargeImageList.ImageSize = new Size(128, 128);
            //    this.listViewPix.LargeImageList.ColorDepth = ColorDepth.Depth32Bit;
            //}

            //Consider doing a better job of re-sizing the image for a better thumbnail...
            //Image imageDragged = Image.FromFile(fileName);

            //Improved square thumbnail sizing...
            //ImageHandler imgHandler = new ImageHandler();
            //Image imageDragged = imgHandler.GetSquareThumbnail(fileName, 128);
            
            Image imageDragged = ImageHandler.GetSquareThumbnail(fileName, 128);

            this.listViewPix.LargeImageList.Images.Add(imageKey, imageDragged);

            // create listviewitem
            //if (sCaption.Length == 0)
            if (string.IsNullOrEmpty(sCaption))
                sCaption = @"<No Caption>";
            ListViewItem item = new ListViewItem(sCaption, fileName);
            item.Name = fileName;
            item.ImageKey = imageKey;
            item.Tag = fileTitle;

            // set checked flag and backcolor depending on whether pic already exists or not
            bool isExisting = isExistingImage(imageKey);
            item.Checked = (isExisting ? false : bChecked);
            item.BackColor = (isExisting ? Color.LightGray : Color.LightGreen);
            
            // add to view
            listViewPix.Items.Add(item);

            //this.listViewPix.Refresh();

            this.buttonUpload.Enabled = true;
            this.labelPictureSize.Enabled = true;
            this.comboBoxPictureSize.Enabled = true;

            imageDragged.Dispose();
            //imgHandler = null;

            return true;
        }
        
        private bool AddFileToListView(string fileName)
        {
            return this.AddFileToListView(fileName, fileName, fileName, Path.GetFileNameWithoutExtension(fileName), true, true);
        }
        
        private void listViewPix_DragEnter(object sender, DragEventArgs e)
        {
            // make sure they're actually dropping files (not text or anything else)
            if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
            {
                // allow them to continue
                // (without this, the cursor stays a "NO" symbol
                e.Effect = DragDropEffects.All;
            }
        }

        private void UploadForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.pix2gallery2Settings.SaveAppSettings();
            if (this.pix2gallery2Settings.lastErrorMessage != "")
            {
                MessageBox.Show("Error: " + this.pix2gallery2Settings.lastErrorMessage);
            }
            Trace.Flush();
        }

        private void UploadForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            //Clear the listview first...
            this.listViewPix.Items.Clear();

            //Cleanup cached files
            if (this.downloadedExisting) this.G2int.CleanupCachedFiles();
        }

        private void treeViewAlbums_AfterSelect(object sender, TreeViewEventArgs e)
        {
            this.labelChooseAlbum.Text = "3. Pictures to Add to " + this.treeViewAlbums.SelectedNode.Text + " Album (Drag and Drop or File-Open)";
            this.listViewPix.Enabled = true;
            this.openToolStripMenuItem.Enabled = true;
            this.cutToolStripMenuItem.Enabled = true;
            this.selectAllToolStripMenuItem.Enabled = true;
            this.getExistingPicturesToolStripMenuItem.Enabled = true;

            if (this.downloadedExisting)
            {
                Regex existingImageRegex = new Regex(@"<Existing>\w*.\w*</Existing>", RegexOptions.Compiled);

                //Remove all existing downloaded pictures
                foreach (ListViewItem lvItem in this.listViewPix.Items)
                {
                    if (existingImageRegex.IsMatch(lvItem.ImageKey))
                    {
                        lvItem.Remove();
                    }

                }
                this.downloadedExisting = false;
                this.toolStripStatusLabel.Text = "";
                this.statusStrip.Refresh();
            }
        }

        private void buttonUpload_Click(object sender, EventArgs e)
        {
            if (G2int == null) return;
            if (this.listViewPix.CheckedItems.Count == 0) return;
            
            this.numFailed = 0;
            int iTot = this.listViewPix.CheckedItems.Count;
            
            this.Cursor = Cursors.WaitCursor;

            //Set the parent, so that the file progress dialog is centered on the parent
            //Need to do this here, before the thread...
            G2int.ParentForm = this;

            this.ThreadedUploadCheckedFiles();

            this.Cursor = Cursors.Default;
            this.toolStripProgressBarUpload.Visible = false;
        }

        //Not used, but kept around for now...
        //private void UploadCheckedFiles()
        //{
        //    int iCurrent = 1;
        //    int successfulUploads = 0;
        //    int failedUploads = 0;

        //    this.toolStripProgressBarUpload.Minimum = 0;
        //    this.toolStripProgressBarUpload.Maximum = this.listViewPix.CheckedItems.Count;
        //    this.toolStripProgressBarUpload.Step = 1;
        //    this.toolStripProgressBarUpload.Visible = true;
        //    this.toolStripStatusLabel.Text = "Uploading first file...";

        //    foreach (ListViewItem itemChecked in this.listViewPix.CheckedItems)
        //    {
        //        string album = this.treeViewAlbums.SelectedNode.Tag.ToString();
        //        string caption = itemChecked.Text;
        //        string filePath = itemChecked.ImageKey;

        //        Application.DoEvents();

        //        //Upload a file...
        //        if (G2int.UploadFileToAlbum(album, caption, filePath))
        //        {
        //            successfulUploads += 1;
        //            this.toolStripStatusLabel.Text = "Uploaded " + filePath + " successfully";
        //            this.statusStrip.Refresh();
        //            itemChecked.Checked = false;
        //        }
        //        else
        //        {
        //            failedUploads += 1;
        //            this.toolStripStatusLabel.Text = "Unsuccessful upload for " + filePath;
        //            this.statusStrip.Refresh();
        //        }

        //        iCurrent += 1;

        //        this.toolStripProgressBarUpload.PerformStep();

        //        Application.DoEvents();
        //    }

        //    if (successfulUploads == 1 && failedUploads == 1)
        //    {
        //        this.toolStripStatusLabel.Text = successfulUploads + " successful upload and " + failedUploads + " failed upload";
        //    }
        //    else if (successfulUploads != 1 && failedUploads == 1)
        //    {
        //        this.toolStripStatusLabel.Text = successfulUploads + " successful uploads and " + failedUploads + " failed upload";
        //    }
        //    else
        //    {
        //        this.toolStripStatusLabel.Text = successfulUploads + " successful uploads and " + failedUploads + " failed uploads";
        //    }
        //    this.statusStrip.Refresh();

        //}

        private void textBoxCaption_TextChanged(object sender, EventArgs e)
        {
            //this.listViewPix.SelectedItems[0].Text = this.textBoxCaption.Text;
            if (this.listViewPix.SelectedItems.Count > 0)
            {
                this.listViewPix.SelectedItems[0].Text = this.textBoxCaption.Text;
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.openFileDialog.ShowDialog() == DialogResult.OK)
            {
                int nonJpeg = 0;
                foreach (String file in this.openFileDialog.FileNames)
                {
                    if (!AddFileToListView(file)) nonJpeg++;
                }

                if (nonJpeg > 0)
                {
                    Trace.WriteLine("FileOpen: Only JPEG files supported. Count of non-JPEG files that were not added is: " + nonJpeg);
                    MessageBox.Show("Sorry, only JPEG files supported. Count of non-JPEG files that were not added is: " + nonJpeg);
                }
            }
        }

        private void SetSuccess(bool success)
        {
            this.success = success;
        }

        private string ResizePicture(string filePath, int sizeIndex)
        {
            if(sizeIndex == 0) return filePath;
            
            int maxWidth;
            int maxHeight;
            string newPath;

            switch (sizeIndex)
            {
                case 1:
                    maxWidth = 1600;
                    maxHeight = 1200;
                    break;
                case 2:
                    maxWidth = 1280;
                    maxHeight = 1024;
                    break;
                case 3:
                    maxWidth = 1024;
                    maxHeight = 768;
                    break;
                case 4:
                    maxWidth = 800;
                    maxHeight = 600;
                    break;
                default:
                    maxWidth = 640;
                    maxHeight = 480;
                    break;
            }

            //ImageHandler imgHandler = new ImageHandler();

            //newPath = imgHandler.ResizePicture_ConstantAspectRatio(filePath, maxWidth, maxHeight);

            //if (imgHandler.resizeError)
            //{
            //    MessageBox.Show("Resize Picture Error - See Log File in " + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
            //    imgHandler = null; 
            //    return filePath;
            //}

            //imgHandler = null;
            newPath = ImageHandler.ResizePicture_ConstantAspectRatio(filePath, maxWidth, maxHeight);
            return newPath;
        }

        //public static Bitmap CreateThumbnail(string lcFilename, int lnWidth, int lnHeight)
        //{conv
        //    System.Drawing.Bitmap bmpOut = null;
        //    try
        //    {
        //        Bitmap loBMP = new Bitmap(lcFilename);
        //        ImageFormat loFormat = loBMP.RawFormat;

        //        decimal lnRatio;
        //        int lnNewWidth = 0;
        //        int lnNewHeight = 0;

        //        //*** If the image is smaller than a thumbnail just return it
        //        if (loBMP.Width < lnWidth && loBMP.Height < lnHeight)
        //            return loBMP;


        //        if (loBMP.Width > loBMP.Height)
        //        {
        //            lnRatio = (decimal)lnWidth / loBMP.Width;
        //            lnNewWidth = lnWidth;
        //            decimal lnTemp = loBMP.Height * lnRatio;
        //            lnNewHeight = (int)lnTemp;
        //        }
        //        else
        //        {
        //            lnRatio = (decimal)lnHeight / loBMP.Height;
        //            lnNewHeight = lnHeight;
        //            decimal lnTemp = loBMP.Width * lnRatio;
        //            lnNewWidth = (int)lnTemp;
        //        }

        //        // System.Drawing.Image imgOut = 
        //        //      loBMP.GetThumbnailImage(lnNewWidth,lnNewHeight,
        //        //                              null,IntPtr.Zero);

        //        // *** This code creates cleaner (though bigger) thumbnails and properly
        //        // *** and handles GIF files better by generating a white background for
        //        // *** transparent images (as opposed to black)
        //        bmpOut = new Bitmap(lnNewWidth, lnNewHeight);
        //        Graphics g = Graphics.FromImage(bmpOut);
        //        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        //        g.FillRectangle(Brushes.White, 0, 0, lnNewWidth, lnNewHeight);
        //        g.DrawImage(loBMP, 0, 0, lnNewWidth, lnNewHeight);

        //        loBMP.Dispose();
        //    }
        //    catch
        //    {
        //        return null;
        //    }

        //    return bmpOut;
        //}

        private int ThreadedUploadCheckedFiles()
        {
            int iCurrent = 1;
            int successfulUploads = 0;
            int failedUploads = 0;
            int iTot = this.listViewPix.CheckedItems.Count;

            this.toolStripProgressBarUpload.Value = 0;
            this.toolStripProgressBarUpload.Minimum = 0;
            this.toolStripProgressBarUpload.Maximum = iTot;
            this.toolStripProgressBarUpload.Step = 1;
            this.toolStripProgressBarUpload.Visible = true;

            foreach (ListViewItem itemChecked in this.listViewPix.CheckedItems)
            {
                this.toolStripProgressBarUpload.PerformStep();

                string album = this.treeViewAlbums.SelectedNode.Name;
                string caption = itemChecked.Text;
                string filePath = itemChecked.Name;
                string newFilePath;

                if (this.comboBoxPictureSize.SelectedIndex > 0)
                {
                    //Resize the picture here and reset the filePath variable...
                    newFilePath = this.ResizePicture(filePath, this.comboBoxPictureSize.SelectedIndex);
                    filePath = newFilePath;
                }

                SetSuccess(true);

                UploadFileThread upThread = new UploadFileThread(album, caption, filePath, Path.GetFileName(filePath), this.G2int, new SetSuccessCallback(SetSuccess));
                Thread t = new Thread(new ThreadStart(upThread.ThreadProc));

                t.Start();
                this.toolStripStatusLabel.Text = "Uploading file " + Path.GetFileName(filePath) + " ";
                t.Join();

                t = null;

                if (this.success)
                {
                    successfulUploads += 1;
                    itemChecked.Checked = false;
                }
                else
                {
                    failedUploads += 1;
                }

                iCurrent += 1;

                //Clean up the resized files in the temp folder...
                if (filePath != itemChecked.ImageKey)
                    File.Delete(filePath);
            }

            if (successfulUploads == 1 && failedUploads == 1)
            {
                this.toolStripStatusLabel.Text = successfulUploads + " successful upload and " + failedUploads + " failed upload ";
            }
            else if (successfulUploads != 1 && failedUploads == 1)
            {
                this.toolStripStatusLabel.Text = successfulUploads + " successful uploads and " + failedUploads + " failed upload ";
            }
            else
            {
                this.toolStripStatusLabel.Text = successfulUploads + " successful uploads and " + failedUploads + " failed uploads ";
            }
            this.statusStrip.Refresh();

            //Added this in just to test the new GetPicturesForAlbum API...
            //NameValueCollection nvPictureList = this.G2int.GetPicturesForAlbum(this.treeViewAlbums.SelectedNode.Name);

            return failedUploads;
        }

        private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem lvItem in this.listViewPix.Items)
            {
                lvItem.Checked = true;
            }
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem lvItem in this.listViewPix.CheckedItems)
            {
                lvItem.Remove();
            }
        }

        private void listViewPix_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete && this.listViewPix.SelectedItems.Count > 0)
            {
                foreach (ListViewItem lvItem in this.listViewPix.SelectedItems)
                {
                    lvItem.Remove();
                }
            }
        }

        private void addAlbumToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddAlbumForm addAlbumForm = new AddAlbumForm(this.G2int);

            AddNodesToAddAlbumForm(addAlbumForm);

            if (addAlbumForm.ShowDialog(this) == DialogResult.OK)
            {
                //Add the album
                if (G2int.CreateNewAlbum(addAlbumForm.textBoxNewAlbum.Text, "", addAlbumForm.treeViewAlbums.SelectedNode.Name))
                {
                    MessageBox.Show("New album " + addAlbumForm.textBoxNewAlbum.Text + " created!");
                    GetAndLoadAlbumsIntoTreeControl();
                }
            }
            addAlbumForm.Dispose();
        }

        private void toolsAddAlbumToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddAlbumForm addAlbumForm = new AddAlbumForm(this.G2int);

            AddNodesToAddAlbumForm(addAlbumForm);

            if (addAlbumForm.ShowDialog(this) == DialogResult.OK)
            {
                //Add the album
                if (G2int.CreateNewAlbum(addAlbumForm.textBoxNewAlbum.Text, "", addAlbumForm.treeViewAlbums.SelectedNode.Name))
                {
                    MessageBox.Show("New album " + addAlbumForm.textBoxNewAlbum.Text + " created!");
                    GetAndLoadAlbumsIntoTreeControl();
                }
            }
            addAlbumForm.Dispose();
        }

        private void AddNodesToAddAlbumForm(AddAlbumForm addAlbumForm)
        {
            if (addAlbumForm == null) return;

            this.Cursor = Cursors.WaitCursor;

            addAlbumForm.treeViewAlbums.BeginUpdate();
            addAlbumForm.treeViewAlbums.Nodes.Clear();
            
            foreach (TreeNode tNode in this.treeViewAlbums.Nodes)
            {
                TreeNode newNode = new TreeNode(tNode.Text);
                newNode.Name = tNode.Name;
                addAlbumForm.treeViewAlbums.Nodes.Add(newNode);
                AddChildNodes(tNode, newNode, addAlbumForm);
            }

            addAlbumForm.treeViewAlbums.ExpandAll();
            addAlbumForm.treeViewAlbums.EndUpdate();
            this.Cursor = Cursors.Default;
        }

        private void AddChildNodes(TreeNode mainParentNode, TreeNode parentNode, AddAlbumForm addAlbumForm)
        {
            foreach (TreeNode tNode in mainParentNode.Nodes)
            {
                TreeNode newNode = new TreeNode(tNode.Text);
                newNode.Name = tNode.Name;
                parentNode.Nodes.Add(newNode);
                AddChildNodes(tNode, newNode, addAlbumForm);
            }
        }

        private void getExistingPicturesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (G2int == null)
            {
                Trace.WriteLine(">> getExistingPicturesToolStripMenuItem_Click G2int == null");
                return;
            }

            Cursor.Current = Cursors.WaitCursor;

            string albumName = this.treeViewAlbums.SelectedNode.Name;
            this.nvExistingPictures = G2int.GetPicturesForAlbum(albumName);

            int iFailures = 0;
            int picCount = Convert.ToInt32(this.nvExistingPictures["image_count"]);
            string baseUri = this.nvExistingPictures["baseurl"];

            this.toolStripProgressBarUpload.Value = 0;
            this.toolStripProgressBarUpload.Minimum = 0;
            this.toolStripProgressBarUpload.Maximum = picCount;
            this.toolStripProgressBarUpload.Step = 1;
            this.toolStripProgressBarUpload.Visible = true;
            
            for (int i = 1; i <= picCount; i++)
            {
                this.toolStripProgressBarUpload.PerformStep();
                this.statusStrip.Refresh();

                string imageName = "image.name." + i.ToString();
                //string imageResizedName = "image.resizedName." + i.ToString();
                string imageThumbName = "image.thumbName." + i.ToString();
                string imageCaption = "image.Caption." + i.ToString();
                string imageTitle = "image.title." + i.ToString();
                string imageExtension = "image.forceExtension." + i.ToString();

                imageName = this.nvExistingPictures[imageName];
                //imageResizedName = this.nvExistingPictures[imageResizedName];
                imageThumbName = this.nvExistingPictures[imageThumbName];
                imageCaption = this.nvExistingPictures[imageCaption];
                imageTitle = this.nvExistingPictures[imageTitle];
                imageExtension = this.nvExistingPictures[imageExtension];

                //At least for now, only downloading the thumbnails unless there isn't one...
                string fileName = imageThumbName;
                if (fileName == null)
                {
                    fileName = imageName;
                }

                string fileUri = baseUri + fileName;

                if (imageExtension != null)
                {
                    fileName = fileName + "." + imageExtension;

                    imageExtension = imageExtension.ToUpper();
                    if (imageExtension != "JPG" && imageExtension != "JPEG")
                    {
                        Trace.WriteLine(">> getExistingPicturesToolStripMenuItem_Click: " + fileName + " was not a JPEG");
                        iFailures++;
                        continue;
                    }
                }
                
                this.toolStripStatusLabel.Text = "Downloading file " + i.ToString() + " of " + picCount.ToString();
                this.statusStrip.Refresh();

                string newFilePath = this.G2int.GetPicture(albumName, fileName, fileUri);

                if (newFilePath != "")
                {
                    this.AddFileToListView(imageName, @"<Existing>" + fileName + @"</Existing>", newFilePath, imageCaption, true, false);
                }
                else
                {
                    iFailures++;
                    MessageBox.Show("Download error for " + imageTitle + " with caption " + imageCaption);
                }
            }

            Cursor.Current = Cursors.Default;

            this.downloadedExisting = true;
            this.toolStripStatusLabel.Text = "Successfully downloaded " + (picCount - iFailures) + " of " + picCount + " existing pictures";
            this.toolStripProgressBarUpload.Visible = false;
            this.statusStrip.Refresh();
        }

        // >> 20070531 SM - Integration with Elements2Pix2Gallery
        private void OpenElements2GalleryForm()
        {
            if (G2int == null)
            {
                MessageBox.Show("You must connect to a gallery first.");
                return;
            }
            Elements2GalleryForm elements2GalleryForm = new Elements2GalleryForm();
            elements2GalleryForm.SetG2Int(G2int);

            //Ted - Setting the size and location of the Elements dialog to match the original dialog
            elements2GalleryForm.Size = this.Size;
            elements2GalleryForm.Location = this.Location;
            //-------
            
            //this.Hide();
            
            elements2GalleryForm.ShowDialog(this);
            
            //elements2GalleryForm.show
            //this.Show();
        }
        private void uploadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //OpenElements2GalleryForm();
        }
        // << 20070531 SM
        // >> 20080122 SM
        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            OpenElements2GalleryForm();
        }

        private void toolStripMenuItem3_Click(object sender, EventArgs e)
        {
            OpenPSE6ToElementsForm();
        }
        private void OpenPSE6ToElementsForm()
        {
            if (G2int == null)
            {
                MessageBox.Show("You must connect to a gallery first.");
                return;
            }
            PSE6ToGalleryForm pse6ToGalleryForm = new PSE6ToGalleryForm();
            pse6ToGalleryForm.SetG2Int(G2int);

            //Ted - Setting the size and location of the Elements dialog to match the original dialog
            pse6ToGalleryForm.Size = this.Size;
            pse6ToGalleryForm.Location = this.Location;
            //-------

            //this.Hide();

            pse6ToGalleryForm.ShowDialog(this);
        }

        // Checks whether an image is a thumbnail of an existing image
        // of the gallery [based on Prefix <Existing> of ImageKey].
        private bool isExistingImage(string imageKey)
        {
            return imageKey.StartsWith(@"<Existing>");
        }

        // Disables the functionality to upload thumbnails of existing pics
        // by unchecking it.
        private void listViewPix_ItemChecked(object sender, ItemCheckedEventArgs e)
        {
            ListViewItem item = e.Item;
            if (isExistingImage(item.ImageKey) && item.Checked)
            {
                item.Checked = false;
                MessageBox.Show(listViewPix, "This picture has already been uploaded in the gallery!"
                    + System.Environment.NewLine + "[Note the light gray background of the caption.]",
                    "Picture already in gallery!",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }
        }
        // << 20080122 SM


    }

    public delegate void SetSuccessCallback(bool failed);

    public class UploadFileThread
    {
        // State information used in the task.
        private string album;
        private string caption;
        private string filePath;
        private string fileName;
        private Gallery2Interface G2int;
        private SetSuccessCallback uploadCallback;

        // The constructor obtains the state information.
        public UploadFileThread(string album, string caption, string filePath, string fileName, Gallery2Interface G2int, SetSuccessCallback uploadCallback)
        {
            this.album = album;
            this.caption = caption;
            this.filePath = filePath;
            this.fileName = fileName;
            this.G2int = G2int;
            this.uploadCallback = uploadCallback;
        }

        public void ThreadProc()
        {
            //>> 20070913 SM
            //bool res = this.G2int.UploadFileToAlbumEvents(this.album, this.caption, this.filePath, this.fileName, true);
            bool res = this.G2int.UploadFileToAlbumEvents(this.album, this.caption, this.filePath, this.fileName, "", "", true);
            //<< 20070913 SM
            //bool res = this.G2int.UploadFileToAlbum(this.album, this.caption, this.filePath, this.fileName);
            if (uploadCallback != null)
                uploadCallback(res);
        }
    }

    public delegate void GetAlbumListCallback(NameValueCollection nvColl);

    public class GetAlbumListThread
    {
        // State information used in the task.
        private Gallery2Interface G2int;
        private GetAlbumListCallback albumListCallback;

        // The constructor obtains the state information.
        public GetAlbumListThread(Gallery2Interface G2int, GetAlbumListCallback albumCallback)
        {
            this.G2int = G2int;
            this.albumListCallback = albumCallback;
        }

        public void ThreadProc()
        {
            if(this.albumListCallback == null) return;

            NameValueCollection nvColl;
            //Get the Gallery Album List
            nvColl = new NameValueCollection(G2int.GetAlbumList());

            albumListCallback(nvColl);
        }
    }
}